Skip to content

fix: Allow Item.Member after HasSingleItem - #6583

Merged
thomhurst merged 1 commit into
thomhurst:mainfrom
SnakyBeaky:fix/hassingleitem-item-member
Aug 11, 2026
Merged

fix: Allow Item.Member after HasSingleItem#6583
thomhurst merged 1 commit into
thomhurst:mainfrom
SnakyBeaky:fix/hassingleitem-item-member

Conversation

@SnakyBeaky

@SnakyBeaky SnakyBeaky commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Description

Ensure TypeErasedAssertion uses the standard assertion execution pipeline, preserving deferred pre-work from HasSingleItem().Item.

Added a regression coverage test for the issue.

Related Issue

Fixes #6581

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Performance improvement
  • Refactoring (no functional changes)

Checklist

Required

  • I have read the Contributing Guidelines
  • If this is a new feature, I started a discussion first and received agreement
  • My code follows the project's code style (modern C# syntax, proper naming conventions)
  • I have written tests that prove my fix is effective or my feature works

Testing

  • All existing tests pass (dotnet test)
  • I have added tests that cover my changes
  • I have tested both source-generated and reflection modes (if applicable)

Summary by CodeRabbit

  • Bug Fixes

    • Fixed member assertions used after single-item assertions so they now complete successfully instead of returning an invalid result.
    • Corrected behavior for both predicate-based and non-predicate member assertions.
  • Tests

    • Added coverage for asynchronous member assertion scenarios following single-item checks.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

TypeErasedAssertion<T> now evaluates through CheckAsync and returns a passed result. Regression tests cover member assertions after HasSingleItem(), with and without a predicate.

Changes

Member assertion fix

Layer / File(s) Summary
Evaluation fix and regression coverage
src/TUnit.Assertions/Conditions/MemberAssertion.cs, tests/TUnit.Assertions.Tests/Bugs/Issue6581Tests.cs
TypeErasedAssertion<T> now uses CheckAsync and returns AssertionResult.Passed after the inner assertion. Issue6581Tests covers direct and predicate-based member assertions after HasSingleItem().

Estimated code review effort: 2 (Simple) | ~10 minutes

Poem

A rabbit checks the member chain,
No null result breaks the train.
Single items now pass through,
Predicates work as they should too.
Hop, hop—tests confirm the fix! 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the primary bug fix: enabling Item.Member after HasSingleItem.
Linked Issues check ✅ Passed The fix uses the standard assertion pipeline and adds regression tests for Item.Member after HasSingleItem, covering both predicate forms [#6581].
Out of Scope Changes check ✅ Passed The changes are limited to the assertion pipeline fix and focused regression tests for the linked issue [#6581].
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Aug 11, 2026

Copy link
Copy Markdown

Greptile Summary

This PR routes type-erased member assertions through the standard assertion pipeline so deferred pre-work is preserved for HasSingleItem().Item.Member(...).

  • Replaces the custom TypeErasedAssertion.AssertAsync() override with a standard CheckAsync() implementation.
  • Adds regression tests for ordinary and predicate-based HasSingleItem() chains.

Confidence Score: 5/5

The PR appears safe to merge, with no actionable correctness or security issues identified.

The changed wrapper preserves deferred pre-work through mapped assertion contexts, executes it once, and continues to propagate inner assertion failures through the existing exception and assertion-scope mechanisms.

Important Files Changed

Filename Overview
src/TUnit.Assertions/Conditions/MemberAssertion.cs Moves type-erased member assertion execution into the base assertion pipeline, preserving mapped pending pre-work without introducing duplicate execution or failure masking.
tests/TUnit.Assertions.Tests/Bugs/Issue6581Tests.cs Adds focused regression coverage for member assertions following both forms of HasSingleItem().Item.

Reviews (1): Last reviewed commit: "fix: Allow Item.Member after HasSingleIt..." | Re-trigger Greptile

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
tests/TUnit.Assertions.Tests/Bugs/Issue6581Tests.cs (1)

13-15: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add failing member-assertion cases.

These tests prove that the chain does not throw for matching values. They do not prove that Member(...).IsEqualTo(...) executes. If the inner assertion were skipped, both tests would still pass. Add negative-path cases with a mismatched member value and the existing assertion-failure helper.

Also applies to: 27-29

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/TUnit.Assertions.Tests/Bugs/Issue6581Tests.cs` around lines 13 - 15,
Add negative-path tests in the affected member-assertion test cases, using a
mismatched member value and the existing assertion-failure helper. Ensure each
case verifies that Member(...).IsEqualTo(...) executes and reports failure,
while preserving the current matching-value coverage.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@tests/TUnit.Assertions.Tests/Bugs/Issue6581Tests.cs`:
- Around line 13-15: Add negative-path tests in the affected member-assertion
test cases, using a mismatched member value and the existing assertion-failure
helper. Ensure each case verifies that Member(...).IsEqualTo(...) executes and
reports failure, while preserving the current matching-value coverage.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6e93d3a9-f5da-404c-8f8e-52710a8c4987

📥 Commits

Reviewing files that changed from the base of the PR and between 5eabbe3 and a804aa5.

📒 Files selected for processing (2)
  • src/TUnit.Assertions/Conditions/MemberAssertion.cs
  • tests/TUnit.Assertions.Tests/Bugs/Issue6581Tests.cs

@thomhurst

Copy link
Copy Markdown
Owner

Thanks @SnakyBeaky !

@thomhurst
thomhurst merged commit b2ce57c into thomhurst:main Aug 11, 2026
11 of 12 checks passed
This was referenced Aug 11, 2026
github-actions Bot pushed a commit to BenjaminMichaelis/TrxLib that referenced this pull request Aug 17, 2026
Updated [TUnit](https://github.com/thomhurst/TUnit) from 1.64.6 to
1.65.0.

<details>
<summary>Release notes</summary>

_Sourced from [TUnit's
releases](https://github.com/thomhurst/TUnit/releases)._

## 1.65.0

<!-- Release notes generated using configuration in .github/release.yml
at v1.65.0 -->

## What's Changed
### Other Changes
* Report unexpected mock generation failures by @​thomhurst in
thomhurst/TUnit#6605
* Process every GenerateMock attribute by @​thomhurst in
thomhurst/TUnit#6606
* Support T.Mock() for static abstract interfaces by @​thomhurst in
thomhurst/TUnit#6607
### Dependencies
* chore(deps): update dependency microsoft.templateengine.authoring.cli
to v10.0.303 by @​thomhurst in
thomhurst/TUnit#6586
* chore(deps): update dependency
microsoft.templateengine.authoring.templateverifier to 10.0.303 by
@​thomhurst in thomhurst/TUnit#6587
* chore(deps): update microsoft.build to 18.9.6 by @​thomhurst in
thomhurst/TUnit#6585
* chore(deps): update dependency fsharp.core to 10.1.400 by @​thomhurst
in thomhurst/TUnit#6588
* chore(deps): update dependency microsoft.entityframeworkcore to
10.0.11 by @​thomhurst in thomhurst/TUnit#6589
* chore(deps): update dependency microsoft.templateengine.authoring.cli
to v10.0.400 by @​thomhurst in
thomhurst/TUnit#6591
* chore(deps): update dependency dotnet-sdk to v10.0.400 by @​thomhurst
in thomhurst/TUnit#6590
* chore(deps): update dependency
microsoft.templateengine.authoring.templateverifier to 10.0.400 by
@​thomhurst in thomhurst/TUnit#6592
* chore(deps): update dependency system.commandline to 2.0.11 by
@​thomhurst in thomhurst/TUnit#6593
* chore(deps): update microsoft.extensions to 10.0.11 by @​thomhurst in
thomhurst/TUnit#6595
* chore(deps): update microsoft.aspnetcore to 10.0.11 by @​thomhurst in
thomhurst/TUnit#6594
* chore(deps): update tunit to 1.64.13 by @​thomhurst in
thomhurst/TUnit#6596
* chore(deps): update dependency nuget.protocol to 7.9.0 by @​thomhurst
in thomhurst/TUnit#6597
* chore(deps): update microsoft.extensions to 10.9.0 by @​thomhurst in
thomhurst/TUnit#6598
* chore(deps): update dependency polyfill to 11.2.0 by @​thomhurst in
thomhurst/TUnit#6601
* chore(deps): update dependency polyfill to 11.2.0 by @​thomhurst in
thomhurst/TUnit#6600
* chore(deps): update dependency
microsoft.testing.extensions.codecoverage to 18.10.0 by @​thomhurst in
thomhurst/TUnit#6602


**Full Changelog**:
thomhurst/TUnit@v1.64.13...v1.65.0

## 1.64.13

<!-- Release notes generated using configuration in .github/release.yml
at v1.64.13 -->

## What's Changed
### Other Changes
* Stabilize immediate WaitsFor assertion test by @​thomhurst in
thomhurst/TUnit#6576
* fix: Allow Item.Member after HasSingleItem by @​SnakyBeaky in
thomhurst/TUnit#6583
### Dependencies
* chore(deps): update tunit to 1.64.6 by @​thomhurst in
thomhurst/TUnit#6577
* chore(deps): update dependency nsubstitute to 6.2.0 by @​thomhurst in
thomhurst/TUnit#6580
* chore(deps): update dependency microsoft.playwright to 1.62.0 by
@​thomhurst in thomhurst/TUnit#6582
* chore(deps): update dependency microsoft.net.stringtools to 18.9.6 by
@​thomhurst in thomhurst/TUnit#6584

## New Contributors
* @​SnakyBeaky made their first contribution in
thomhurst/TUnit#6583

**Full Changelog**:
thomhurst/TUnit@v1.64.6...v1.64.13

Commits viewable in [compare
view](thomhurst/TUnit@v1.64.6...v1.65.0).
</details>

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=TUnit&package-manager=nuget&previous-version=1.64.6&new-version=1.65.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
github-actions Bot pushed a commit to IntelliTect/CodingGuidelines that referenced this pull request Aug 17, 2026
Updated [TUnit.Core](https://github.com/thomhurst/TUnit) from 1.64.6 to
1.65.0.

<details>
<summary>Release notes</summary>

_Sourced from [TUnit.Core's
releases](https://github.com/thomhurst/TUnit/releases)._

## 1.65.0

<!-- Release notes generated using configuration in .github/release.yml
at v1.65.0 -->

## What's Changed
### Other Changes
* Report unexpected mock generation failures by @​thomhurst in
thomhurst/TUnit#6605
* Process every GenerateMock attribute by @​thomhurst in
thomhurst/TUnit#6606
* Support T.Mock() for static abstract interfaces by @​thomhurst in
thomhurst/TUnit#6607
### Dependencies
* chore(deps): update dependency microsoft.templateengine.authoring.cli
to v10.0.303 by @​thomhurst in
thomhurst/TUnit#6586
* chore(deps): update dependency
microsoft.templateengine.authoring.templateverifier to 10.0.303 by
@​thomhurst in thomhurst/TUnit#6587
* chore(deps): update microsoft.build to 18.9.6 by @​thomhurst in
thomhurst/TUnit#6585
* chore(deps): update dependency fsharp.core to 10.1.400 by @​thomhurst
in thomhurst/TUnit#6588
* chore(deps): update dependency microsoft.entityframeworkcore to
10.0.11 by @​thomhurst in thomhurst/TUnit#6589
* chore(deps): update dependency microsoft.templateengine.authoring.cli
to v10.0.400 by @​thomhurst in
thomhurst/TUnit#6591
* chore(deps): update dependency dotnet-sdk to v10.0.400 by @​thomhurst
in thomhurst/TUnit#6590
* chore(deps): update dependency
microsoft.templateengine.authoring.templateverifier to 10.0.400 by
@​thomhurst in thomhurst/TUnit#6592
* chore(deps): update dependency system.commandline to 2.0.11 by
@​thomhurst in thomhurst/TUnit#6593
* chore(deps): update microsoft.extensions to 10.0.11 by @​thomhurst in
thomhurst/TUnit#6595
* chore(deps): update microsoft.aspnetcore to 10.0.11 by @​thomhurst in
thomhurst/TUnit#6594
* chore(deps): update tunit to 1.64.13 by @​thomhurst in
thomhurst/TUnit#6596
* chore(deps): update dependency nuget.protocol to 7.9.0 by @​thomhurst
in thomhurst/TUnit#6597
* chore(deps): update microsoft.extensions to 10.9.0 by @​thomhurst in
thomhurst/TUnit#6598
* chore(deps): update dependency polyfill to 11.2.0 by @​thomhurst in
thomhurst/TUnit#6601
* chore(deps): update dependency polyfill to 11.2.0 by @​thomhurst in
thomhurst/TUnit#6600
* chore(deps): update dependency
microsoft.testing.extensions.codecoverage to 18.10.0 by @​thomhurst in
thomhurst/TUnit#6602


**Full Changelog**:
thomhurst/TUnit@v1.64.13...v1.65.0

## 1.64.13

<!-- Release notes generated using configuration in .github/release.yml
at v1.64.13 -->

## What's Changed
### Other Changes
* Stabilize immediate WaitsFor assertion test by @​thomhurst in
thomhurst/TUnit#6576
* fix: Allow Item.Member after HasSingleItem by @​SnakyBeaky in
thomhurst/TUnit#6583
### Dependencies
* chore(deps): update tunit to 1.64.6 by @​thomhurst in
thomhurst/TUnit#6577
* chore(deps): update dependency nsubstitute to 6.2.0 by @​thomhurst in
thomhurst/TUnit#6580
* chore(deps): update dependency microsoft.playwright to 1.62.0 by
@​thomhurst in thomhurst/TUnit#6582
* chore(deps): update dependency microsoft.net.stringtools to 18.9.6 by
@​thomhurst in thomhurst/TUnit#6584

## New Contributors
* @​SnakyBeaky made their first contribution in
thomhurst/TUnit#6583

**Full Changelog**:
thomhurst/TUnit@v1.64.6...v1.64.13

Commits viewable in [compare
view](thomhurst/TUnit@v1.64.6...v1.65.0).
</details>

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=TUnit.Core&package-manager=nuget&previous-version=1.64.6&new-version=1.65.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: .Item.Member(...) after .HasSingleItem() throws InvalidOperationException

2 participants